function HTMLescape(string)  {  
      if (!string){return ""} else {
         var LT = new RegExp("<", "g");  
         var GT = new RegExp(">", "g");  
         var AMP = new RegExp("&", "g");  
         var TAB = new RegExp("\t", "g");
         return  string.replace(AMP,"&amp;").replace(LT, "&lt;").replace(GT, "&gt;").replace(TAB, "...");
      }
}  

function SOMEescape(string)  {  
      if (!string){return ""} else {
         var LT = new RegExp("<", "g");  
         var GT = new RegExp(">", "g");  
         var AMP = new RegExp("&", "g");  
         var TAB = new RegExp("\t", "g");
         return  string.replace(AMP,escape("&")).replace(LT, escape("<")).replace(GT, escape(">")).replace(TAB, escape("\t"));
      }
}

CmdUtils.CreateCommand({  
    name: "whatizit",  
    takes: {"selected text": noun_arb_text},  
    execute: function(directObj) {},    
    preview: function(pblock, directObj) {

      var pipe="whatizitEBIMed";//"whatizitEBIMedDiseaseChemicals";
      var inputText=SOMEescape(CmdUtils.getSelection());

      var soap = '<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:wz="http://www.ebi.ac.uk/webservices/whatizit/ws"> ' +  
                  '    <soap:Body> ' +  
    '        <wz:contact> '+      
    '            <pipelineName>'+pipe+'</pipelineName> ' +
    '            <text>' + inputText + '</text> ' +
    '            <convertToHtml>false</convertToHtml> ' +  
    '        </wz:contact> ' +  
    '     </soap:Body> ' +  
    '</soap:Envelope> ';

      var url="http://www.ebi.ac.uk:80/webservices/whatizit/ws";

      jQuery.ajax({  
        type:     'POST',  
        url:      url,  
        dataType: "xml",
        contentType: "text/xml",
        data:     soap,
        success: function(response) {
             pblock.innerHTML = "analyzing tagged document...";
             var serializer = new window.XMLSerializer();
             var parser = new window.DOMParser();
             xml=parser.parseFromString(jQuery(response).find("ns1\\:contactResponse return").text(),"text/xml");

             var tags={uniprot: "z\\:uniprot", go: "z\\:go", species:"z\\:species"};//, drugs: "z\\:drug", disease:"z\\:disease", compound: "z\\:e"
             var terms={};
             var count={};
             var inSentence={};
             for (t in tags){
               terms[t]=[];
               count[t]=[];
               inSentence[t]=[];
               jQuery(xml).find("SENT").each(function(i){//for each sentence
                 var sid=jQuery(this).attr("sid");//sentence id
                 var elements=jQuery(this).find(tags[t]);
                 elements.each(function(i){
                   var ids=jQuery(this).attr("ids");
                   if (!terms[t][ids]){terms[t][ids]=jQuery(this).text()};
                   
                   //there might be various instances of a entity
                   //we should keep order in sentence of instance
                   if (count[t][ids]){count[t][ids]++} else {count[t][ids]=1};
                   if (!inSentence[t][ids]){inSentence[t][ids]=[]};
                   if (inSentence[t][ids].indexOf(sid)<0){inSentence[t][ids].push(sid)};
                   //offset=?;
                   //termLocation[t][ids].push({sentence: sid, offset: offset});
                 });
               });
             };

             var sentences={};
             jQuery(xml).find("SENT").each(function(i){
               //will need to replace <z:*> tags by <span class="tag*" id="inlineTag*XXX">
               var sentence=jQuery(this).text();
               var sid=jQuery(this).attr("sid");
               sentences[sid]=sentence;
             });

             var doc=pblock.ownerDocument;
             doc.inSentence=inSentence;
             doc.sentences=sentences;
             doc.showSentences=function(id,tagType,term){
               var html="<ul>";
               list=inSentence[tagType][id];
               for (var i in list){
                 var re= new RegExp(term+"\\b","gi");
                 html+="<li>"+sentences[list[i]].replace(re,"<span class='hi'>"+term+"</span>")+"</li>"
               };
               html+="</ul>"
               return html;
             };

             //from http://news.hping.org/comp.lang.javascript.archive/0867.html
             function sortAssoc(aInput){
               var aTemp = [];
               for (var sKey in aInput)
                 aTemp.push([sKey, aInput[sKey]]);
                 aTemp.sort(function () {return arguments[0][1] > arguments[1][1]});
                 var aOutput = [];
                 for (var nIndex = aTemp.length-1; nIndex >=0; nIndex--)
                 aOutput[aTemp[nIndex][0]] = aTemp[nIndex][1];
               return aOutput;
             };
 
             var style="<style type='text/css'>.cloudSection {padding:10px 5px} .title {font: small-caps bold 12px arial; background:white; color: black; padding: 2px 2px} .cloud{padding:5px 5px; background:white; color: #666666; font: arial} .reactive:hover{cursor: pointer; color: blue; text-decoration:underline} .hi{text-decoration:underline; color: orange}</style>";
             var html="";
             for (t in tags){            
               var sorted=sortAssoc(count[t]);
               html+="<div class='cloudSection'><span class='title'>"+t+"</span><br/>";
               html+="<div class='cloud'>";
               for (id in sorted){
                  var term=terms[t][id];
                  var n=sorted[id];
                  var size=12+5*Math.round(Math.log(Math.min(n,10)));//rather empirical...
                  html+="<span style='font-size:"+size+"px' class='reactive' onmouseover='document.getElementById(\"sentences\").innerHTML=showSentences(\""+id+"\",\""+t+"\",\""+term+"\")'>"+term+"</span> ";
               };
               html+="</div></div>";
             };
             html+="<div id='sentences'></div>";
             pblock.innerHTML = style+
                                //"<code>"+HTMLescape(serializer.serializeToString(xml))+"</code>"+"<br/><br/>"+
                                html;          
        },
        error: function(XMLHttpRequest, status, errorThrown){pblock.innerHTML = 'status: '+status;}
      })
   }  
})